/**
  * Author: Mei
  * Date: 2021-01-07 15:20
  * Description: 改进的观察者模式
  * 1、继承是强对象关系，不够灵活
  * 2、观察者被通知的接口参数不支持变化，导致观察者不能应付接口的变化
  *
  */

#include "../head.h"
#include "../NonCopyable.cpp"

template<typename Func>
class Events : NonCopyable {
public:
    Events() {
    }

    //注册观察者
    int connect( Func &f) {
        return Assign(move(f));
    }

    int connect(Func &&f) {
        return Assign(forward<Func>(f));
    }

    //移除观察者
    void Disconnect(int key) {
        m_connections.erase(key);
    }

    //通知所有观察者
    template<typename ...Args>
    void Notify(Args &&...args) {
        for (auto &it : m_connections) {
            it.second(forward<Args>(args)...);
        }
    }

private:
    int Assign(Func &&f) {
        int k = m_observerId++;
        m_connections.emplace(k, forward<Func>(f));
        return k;
    }

private:
    int m_observerId = 0;
    map<int, Func> m_connections;
};

//测试
struct A {
    int a, b;

    void print(int a, int b) {
        cout << a << ", " << b << endl;
    }
};

void print(int a, int b) {
    cout << a << ", " << b << endl;
}

int main() {
    Events<function<void(int, int)>> myevent;
    auto key = myevent.connect(print);

    A t;
    auto lambdaKey = myevent.connect([&t](int a, int b) {
        t.a = a;
        t.b = b;
    });

    function<void(int, int)> f = bind(&A::print, &t, placeholders::_1, placeholders::_2);
    myevent.connect(f);

    int a = 1;
    int b = 2;
    myevent.Notify(a, b);

    //移除观察者
    myevent.Disconnect(key);
    return 0;
}